<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta name="generator" content="Hugo 0.74.1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>spring boot 扫码登录 后端实现 | caijinglong的博客</title>
    <meta property="og:title" content="spring boot 扫码登录 后端实现 - caijinglong的博客">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content="2017-08-25T11:42:26&#43;08:00">
        
        
    <meta property="article:modified_time" content="2017-08-25T11:42:26&#43;08:00">
        
    <meta name="Keywords" content="golang,go语言,flutter,caijinglong,java,android,博客,项目管理,python,软件架构,公众号,小程序">
    <meta name="description" content="spring boot 扫码登录 后端实现">
        
    <meta name="author" content="caijinglong">
    <meta property="og:url" content="http://www.kikt.top/posts/server/java/spring-boot/scan-login/">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">

    <link rel="stylesheet" href="/css/normalize.css">
    
        <link rel="stylesheet" href="/css/prism.css">
    
    <link rel="stylesheet" href="/css/style.css">
    <script type="text/javascript" src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    

   
    <script>
        (function(){
            var bp = document.createElement('script');
            var curProtocol = window.location.protocol.split(':')[0];
            if (curProtocol === 'https') {
                bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
            }
            else {
                bp.src = 'http://push.zhanzhang.baidu.com/push.js';
            }
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(bp, s);
        })();
    </script>

    
    
</head>

<body>
<header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="http://www.kikt.top">
                        caijinglong的博客
                    </a>
                
                <p class="description">Android/Flutter开发者，对于golang/python/ios/java 均有所了解</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="" href="http://www.kikt.top">首页</a>
                    
                    <a  href="http://www.kikt.top/archives/" title="归档">归档</a>
                    
                    <a  href="http://www.kikt.top/contact/" title="接单">接单</a>
                    
                    <a  href="http://www.kikt.top/about/" title="关于">关于</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>


<div id="body">
    <div class="container">
        <div class="col-group">

            <div class="col-8" id="main">
                <div class="res-cons">
                    <article class="post">
                        <header>
                            <h1 class="post-title">spring boot 扫码登录 后端实现</h1>
                        </header>
                        <date class="post-meta meta-date">
                            2017年8月25日
                        </date>
                        
                        <div class="post-meta meta-category">
                            |
                            
                                <a href="http://www.kikt.top/categories/spring">spring</a>
                            
                                <a href="http://www.kikt.top/categories/java">java</a>
                            
                                <a href="http://www.kikt.top/categories/server">server</a>
                            
                        </div>
                        
                        
                        <div class="post-meta">
                            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span> 阅读</span></span>
                        </div>
                        
                        <div class="post-content">
                            <h2 id="前言">前言</h2>
<p>在业内，扫码登陆不是什么新技术了，我这里主要是想自己实现一下这个功能，用的是简单实现，提供的只是思路
具体可以参考网上的其他文章
<a href="http://www.jianshu.com/p/7f072ac61763">扫码登录是如何实现的？</a></p>
<h2 id="开发环境">开发环境</h2>
<pre><code>mac+idea+paw+chrome+mysql
开发语言:java+kotlin

mac:我的开发系统
idea:开发工具
paw:http调试工具
</code></pre>
<h3 id="插一句">插一句</h3>
<pre><code>开发语言使用kotlin是有原因,kotlin是构建在jvm上的,而且有很多很方便的语法糖,敲代码速度很快
</code></pre>
<h3 id="启动项目">启动项目</h3>
<p>首先配置一个 spring boot 的项目,这里使用 maven 构建的方案,因为我这里使用 gradle 构建总是会出现各种奇怪的问题</p>
<p>pom.xml</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-xml" data-lang="xml"><span style="color:#75715e">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
<span style="color:#f92672">&lt;project</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#34;http://maven.apache.org/POM/4.0.0&#34;</span> <span style="color:#a6e22e">xmlns:xsi=</span><span style="color:#e6db74">&#34;http://www.w3.org/2001/XMLSchema-instance&#34;</span>
         <span style="color:#a6e22e">xsi:schemaLocation=</span><span style="color:#e6db74">&#34;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&#34;</span><span style="color:#f92672">&gt;</span>
    <span style="color:#f92672">&lt;modelVersion&gt;</span>4.0.0<span style="color:#f92672">&lt;/modelVersion&gt;</span>

    <span style="color:#f92672">&lt;groupId&gt;</span>com.kikt<span style="color:#f92672">&lt;/groupId&gt;</span>
    <span style="color:#f92672">&lt;artifactId&gt;</span>myapp<span style="color:#f92672">&lt;/artifactId&gt;</span>
    <span style="color:#f92672">&lt;version&gt;</span>0.0.1-SNAPSHOT<span style="color:#f92672">&lt;/version&gt;</span>
    <span style="color:#75715e">&lt;!--&lt;packaging&gt;war&lt;/packaging&gt;--&gt;</span>
    <span style="color:#f92672">&lt;packaging&gt;</span>war<span style="color:#f92672">&lt;/packaging&gt;</span>

    <span style="color:#f92672">&lt;name&gt;</span>myapp<span style="color:#f92672">&lt;/name&gt;</span>
    <span style="color:#f92672">&lt;description&gt;</span>MyApp<span style="color:#f92672">&lt;/description&gt;</span>

    <span style="color:#f92672">&lt;parent&gt;</span>
        <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
        <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-parent<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;version&gt;</span>1.5.4.RELEASE<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;relativePath/&gt;</span> <span style="color:#75715e">&lt;!-- lookup parent from repository --&gt;</span>
    <span style="color:#f92672">&lt;/parent&gt;</span>

    <span style="color:#f92672">&lt;properties&gt;</span>
        <span style="color:#f92672">&lt;project.build.sourceEncoding&gt;</span>UTF-8<span style="color:#f92672">&lt;/project.build.sourceEncoding&gt;</span>
        <span style="color:#f92672">&lt;project.reporting.outputEncoding&gt;</span>UTF-8<span style="color:#f92672">&lt;/project.reporting.outputEncoding&gt;</span>
        <span style="color:#f92672">&lt;java.version&gt;</span>1.8<span style="color:#f92672">&lt;/java.version&gt;</span>
        <span style="color:#f92672">&lt;kotlin.version&gt;</span>1.1.3-2<span style="color:#f92672">&lt;/kotlin.version&gt;</span>
    <span style="color:#f92672">&lt;/properties&gt;</span>

    <span style="color:#f92672">&lt;dependencies&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;dependency&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;/dependency&gt;--&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-data-rest<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-web<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>mysql<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>mysql-connector-java<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>runtime<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>com.alibaba<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>druid<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.1.0<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-tomcat<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#75715e">&lt;!--&lt;scope&gt;provided&lt;/scope&gt;--&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-actuator<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#75715e">&lt;!--&lt;scope&gt;provided&lt;/scope&gt;--&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-test<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>test<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#75715e">&lt;!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;dependency&gt;--&gt;</span>
            <span style="color:#75715e">&lt;!--&lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;--&gt;</span>
            <span style="color:#75715e">&lt;!--&lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;--&gt;</span>
            <span style="color:#75715e">&lt;!--&lt;version&gt;1.3.0&lt;/version&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;/dependency&gt;--&gt;</span>


        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-aop<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-data-jpa<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.5.4.RELEASE<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.jetbrains.kotlin<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>kotlin-stdlib-jre8<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>${kotlin.version}<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.jetbrains.kotlin<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>kotlin-test<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>${kotlin.version}<span style="color:#f92672">&lt;/version&gt;</span>
            <span style="color:#f92672">&lt;scope&gt;</span>test<span style="color:#f92672">&lt;/scope&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#75715e">&lt;!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>com.alibaba<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>fastjson<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>1.2.35<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#75715e">&lt;!-- https://mvnrepository.com/artifact/org.json/json --&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.json<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>json<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>20170516<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-jdbc<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;exclusions&gt;</span>
                <span style="color:#f92672">&lt;exclusion&gt;</span>
                    <span style="color:#f92672">&lt;groupId&gt;</span>org.apache.tomcat<span style="color:#f92672">&lt;/groupId&gt;</span>
                    <span style="color:#f92672">&lt;artifactId&gt;</span>tomcat-jdbc<span style="color:#f92672">&lt;/artifactId&gt;</span>
                <span style="color:#f92672">&lt;/exclusion&gt;</span>
            <span style="color:#f92672">&lt;/exclusions&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-starter-thymeleaf<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-devtools<span style="color:#f92672">&lt;/artifactId&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>

        <span style="color:#75715e">&lt;!--&lt;dependency&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;artifactId&gt;spring-boot-starter-ssl&lt;/artifactId&gt;--&gt;</span>
        <span style="color:#75715e">&lt;!--&lt;/dependency&gt;--&gt;</span>

        <span style="color:#75715e">&lt;!--netty--&gt;</span>
        <span style="color:#f92672">&lt;dependency&gt;</span>
            <span style="color:#f92672">&lt;groupId&gt;</span>io.netty<span style="color:#f92672">&lt;/groupId&gt;</span>
            <span style="color:#f92672">&lt;artifactId&gt;</span>netty-all<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;version&gt;</span>4.1.13.Final<span style="color:#f92672">&lt;/version&gt;</span>
        <span style="color:#f92672">&lt;/dependency&gt;</span>
    <span style="color:#f92672">&lt;/dependencies&gt;</span>

    <span style="color:#f92672">&lt;build&gt;</span>
        <span style="color:#f92672">&lt;finalName&gt;</span>myapp<span style="color:#f92672">&lt;/finalName&gt;</span>
        <span style="color:#f92672">&lt;plugins&gt;</span>
            <span style="color:#f92672">&lt;plugin&gt;</span>
                <span style="color:#f92672">&lt;groupId&gt;</span>org.springframework.boot<span style="color:#f92672">&lt;/groupId&gt;</span>
                <span style="color:#f92672">&lt;artifactId&gt;</span>spring-boot-maven-plugin<span style="color:#f92672">&lt;/artifactId&gt;</span>
            <span style="color:#f92672">&lt;/plugin&gt;</span>
            <span style="color:#f92672">&lt;plugin&gt;</span>
                <span style="color:#f92672">&lt;groupId&gt;</span>org.jetbrains.kotlin<span style="color:#f92672">&lt;/groupId&gt;</span>
                <span style="color:#f92672">&lt;artifactId&gt;</span>kotlin-maven-plugin<span style="color:#f92672">&lt;/artifactId&gt;</span>
                <span style="color:#f92672">&lt;version&gt;</span>${kotlin.version}<span style="color:#f92672">&lt;/version&gt;</span>
                <span style="color:#f92672">&lt;executions&gt;</span>
                    <span style="color:#f92672">&lt;execution&gt;</span>
                        <span style="color:#f92672">&lt;id&gt;</span>compile<span style="color:#f92672">&lt;/id&gt;</span>
                        <span style="color:#f92672">&lt;phase&gt;</span>compile<span style="color:#f92672">&lt;/phase&gt;</span>
                        <span style="color:#f92672">&lt;goals&gt;</span>
                            <span style="color:#f92672">&lt;goal&gt;</span>compile<span style="color:#f92672">&lt;/goal&gt;</span>
                        <span style="color:#f92672">&lt;/goals&gt;</span>
                    <span style="color:#f92672">&lt;/execution&gt;</span>
                    <span style="color:#f92672">&lt;execution&gt;</span>
                        <span style="color:#f92672">&lt;id&gt;</span>test-compile<span style="color:#f92672">&lt;/id&gt;</span>
                        <span style="color:#f92672">&lt;phase&gt;</span>test-compile<span style="color:#f92672">&lt;/phase&gt;</span>
                        <span style="color:#f92672">&lt;goals&gt;</span>
                            <span style="color:#f92672">&lt;goal&gt;</span>test-compile<span style="color:#f92672">&lt;/goal&gt;</span>
                        <span style="color:#f92672">&lt;/goals&gt;</span>
                    <span style="color:#f92672">&lt;/execution&gt;</span>
                <span style="color:#f92672">&lt;/executions&gt;</span>
                <span style="color:#f92672">&lt;configuration&gt;</span>
                    <span style="color:#f92672">&lt;jvmTarget&gt;</span>1.8<span style="color:#f92672">&lt;/jvmTarget&gt;</span>
                <span style="color:#f92672">&lt;/configuration&gt;</span>
            <span style="color:#f92672">&lt;/plugin&gt;</span>
            <span style="color:#f92672">&lt;plugin&gt;</span>
                <span style="color:#f92672">&lt;groupId&gt;</span>org.apache.maven.plugins<span style="color:#f92672">&lt;/groupId&gt;</span>
                <span style="color:#f92672">&lt;artifactId&gt;</span>maven-compiler-plugin<span style="color:#f92672">&lt;/artifactId&gt;</span>
                <span style="color:#f92672">&lt;executions&gt;</span>
                    <span style="color:#f92672">&lt;execution&gt;</span>
                        <span style="color:#f92672">&lt;id&gt;</span>compile<span style="color:#f92672">&lt;/id&gt;</span>
                        <span style="color:#f92672">&lt;phase&gt;</span>compile<span style="color:#f92672">&lt;/phase&gt;</span>
                        <span style="color:#f92672">&lt;goals&gt;</span>
                            <span style="color:#f92672">&lt;goal&gt;</span>compile<span style="color:#f92672">&lt;/goal&gt;</span>
                        <span style="color:#f92672">&lt;/goals&gt;</span>
                    <span style="color:#f92672">&lt;/execution&gt;</span>
                    <span style="color:#f92672">&lt;execution&gt;</span>
                        <span style="color:#f92672">&lt;id&gt;</span>testCompile<span style="color:#f92672">&lt;/id&gt;</span>
                        <span style="color:#f92672">&lt;phase&gt;</span>test-compile<span style="color:#f92672">&lt;/phase&gt;</span>
                        <span style="color:#f92672">&lt;goals&gt;</span>
                            <span style="color:#f92672">&lt;goal&gt;</span>testCompile<span style="color:#f92672">&lt;/goal&gt;</span>
                        <span style="color:#f92672">&lt;/goals&gt;</span>
                    <span style="color:#f92672">&lt;/execution&gt;</span>
                <span style="color:#f92672">&lt;/executions&gt;</span>
            <span style="color:#f92672">&lt;/plugin&gt;</span>
        <span style="color:#f92672">&lt;/plugins&gt;</span>
    <span style="color:#f92672">&lt;/build&gt;</span>
    <span style="color:#f92672">&lt;repositories&gt;</span>
        <span style="color:#f92672">&lt;repository&gt;</span>
            <span style="color:#f92672">&lt;id&gt;</span>spring-milestone<span style="color:#f92672">&lt;/id&gt;</span>
            <span style="color:#f92672">&lt;url&gt;</span>http://repo.spring.io/libs-release<span style="color:#f92672">&lt;/url&gt;</span>
        <span style="color:#f92672">&lt;/repository&gt;</span>
    <span style="color:#f92672">&lt;/repositories&gt;</span>

<span style="color:#f92672">&lt;/project&gt;</span>

</code></pre></div><p>其中有一些是其他的配置,比如 netty 是在内部构建一个 netty 服务器,注入 spring 进行管理</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#66d9ef">server</span>:
  <span style="color:#66d9ef">port</span>: <span style="color:#ae81ff">8433</span>
  <span style="color:#66d9ef">tomcat</span>:
    <span style="color:#66d9ef">uri-encoding</span>: utf<span style="color:#ae81ff">-8</span>

<span style="color:#66d9ef">spring</span>:
  <span style="color:#66d9ef">datasource</span>:
    <span style="color:#66d9ef">url</span>: jdbc:mysql://localhost:<span style="color:#ae81ff">3306</span>/app?autoReconnect=<span style="color:#66d9ef">true</span><span style="color:#75715e">&amp;useUnicode=true&amp;characterEncoding=utf-8</span>
    <span style="color:#66d9ef">username</span>: root
    <span style="color:#66d9ef">password</span>: root
    <span style="color:#66d9ef">driver-class-name</span>: com.mysql.jdbc.Driver
  <span style="color:#75715e">#    type: com.alibaba.druid.pool.DruidDataSource</span>
  <span style="color:#66d9ef">profiles</span>:
    <span style="color:#66d9ef">active</span>: dev
  <span style="color:#75715e">#    active: prod</span>
  <span style="color:#75715e">#    active: test</span>
  <span style="color:#75715e">#jpg</span>
  <span style="color:#66d9ef">jpa</span>:
    <span style="color:#66d9ef">database</span>: mysql
    <span style="color:#66d9ef">show-sql</span>: <span style="color:#66d9ef">true</span>
    <span style="color:#66d9ef">hibernate</span>:
      <span style="color:#66d9ef">ddl-auto</span>: update
  <span style="color:#66d9ef">jooq</span>:
    <span style="color:#66d9ef">sql-dialect</span>:
  <span style="color:#75715e">#thymeleaf</span>
  <span style="color:#66d9ef">thymeleaf</span>:
    <span style="color:#66d9ef">mode</span>: HTML5
<span style="color:#75715e">#mybatis:</span>
<span style="color:#75715e">#  mapperLocations: classpath:mapper/*.xml</span>
<span style="color:#75715e">#  type-aliases-package: com.kikt.api.responsedata</span>
</code></pre></div><p>配置文件,使用的是 yml 的格式,也算比较容易理解吧</p>
<h3 id="首先配置几个-controller">首先配置几个 Controller</h3>
<p>除网页外,其他所有的交互方式使用 restful 的方式</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#a6e22e">@RestController</span>
<span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;/user&#34;</span><span style="color:#f92672">)</span>
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">UserCtl</span> <span style="color:#66d9ef">extends</span> BaseCtl <span style="color:#f92672">{</span>

    <span style="color:#a6e22e">@Autowired</span>
    <span style="color:#66d9ef">private</span> ScanService scanService<span style="color:#f92672">;</span>

    <span style="color:#a6e22e">@Autowired</span>
    <span style="color:#66d9ef">private</span> LoginService loginService<span style="color:#f92672">;</span>

    <span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/login/{username}&#34;</span><span style="color:#f92672">,</span> method <span style="color:#f92672">=</span> RequestMethod<span style="color:#f92672">.</span><span style="color:#a6e22e">POST</span><span style="color:#f92672">)</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">login</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@PathVariable</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;username&#34;</span><span style="color:#f92672">)</span> String username<span style="color:#f92672">,</span> <span style="color:#a6e22e">@RequestParam</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;pwd&#34;</span><span style="color:#f92672">)</span> String pwd<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        <span style="color:#66d9ef">return</span> loginService<span style="color:#f92672">.</span><span style="color:#a6e22e">login</span><span style="color:#f92672">(</span>username<span style="color:#f92672">,</span> pwd<span style="color:#f92672">);</span>
    <span style="color:#f92672">}</span>

    <span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/login&#34;</span><span style="color:#f92672">,</span> method <span style="color:#f92672">=</span> RequestMethod<span style="color:#f92672">.</span><span style="color:#a6e22e">GET</span><span style="color:#f92672">)</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">index</span><span style="color:#f92672">(</span>Model model<span style="color:#f92672">,</span> HttpServletRequest request<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        String sessionId <span style="color:#f92672">=</span> scanService<span style="color:#f92672">.</span><span style="color:#a6e22e">getSessionId</span><span style="color:#f92672">();</span>
        String scheme <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getScheme</span><span style="color:#f92672">();</span>
        logger<span style="color:#f92672">.</span><span style="color:#a6e22e">debug</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;URL:&#34;</span> <span style="color:#f92672">+</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getRequestURL</span><span style="color:#f92672">());</span>
        String serverName <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getServerName</span><span style="color:#f92672">();</span>
        logger<span style="color:#f92672">.</span><span style="color:#a6e22e">debug</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;addr:&#34;</span> <span style="color:#f92672">+</span> serverName<span style="color:#f92672">);</span>
        String contextPath <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getContextPath</span><span style="color:#f92672">();</span>
        logger<span style="color:#f92672">.</span><span style="color:#a6e22e">debug</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;contextPath:&#34;</span> <span style="color:#f92672">+</span> contextPath<span style="color:#f92672">);</span>
        <span style="color:#66d9ef">int</span> serverPort <span style="color:#f92672">=</span> request<span style="color:#f92672">.</span><span style="color:#a6e22e">getServerPort</span><span style="color:#f92672">();</span>
        logger<span style="color:#f92672">.</span><span style="color:#a6e22e">debug</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;serverport:&#34;</span> <span style="color:#f92672">+</span> serverPort<span style="color:#f92672">);</span>

        StringBuilder path <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> StringBuilder<span style="color:#f92672">();</span>
        path<span style="color:#f92672">.</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span>scheme<span style="color:#f92672">).</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;://&#34;</span><span style="color:#f92672">).</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span>serverName<span style="color:#f92672">).</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;:&#34;</span><span style="color:#f92672">).</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span>serverPort<span style="color:#f92672">).</span><span style="color:#a6e22e">append</span><span style="color:#f92672">(</span>contextPath<span style="color:#f92672">);</span>

        model<span style="color:#f92672">.</span><span style="color:#a6e22e">addAttribute</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;sessionId&#34;</span><span style="color:#f92672">,</span> sessionId<span style="color:#f92672">);</span>
        model<span style="color:#f92672">.</span><span style="color:#a6e22e">addAttribute</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;qrcode&#34;</span><span style="color:#f92672">,</span> path <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/user/login/&#34;</span> <span style="color:#f92672">+</span> sessionId<span style="color:#f92672">);</span>
        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;index&#34;</span><span style="color:#f92672">;</span>
    <span style="color:#f92672">}</span>

    <span style="color:#75715e">//for html wait login
</span><span style="color:#75715e"></span>    <span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/wait/{sessionId}&#34;</span><span style="color:#f92672">,</span> method <span style="color:#f92672">=</span> RequestMethod<span style="color:#f92672">.</span><span style="color:#a6e22e">POST</span><span style="color:#f92672">)</span>
    <span style="color:#a6e22e">@ResponseBody</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">waitLogin</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@PathVariable</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;sessionId&#34;</span><span style="color:#f92672">)</span> String sessionId<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        <span style="color:#66d9ef">return</span> scanService<span style="color:#f92672">.</span><span style="color:#a6e22e">waitForLogin</span><span style="color:#f92672">(</span>sessionId<span style="color:#f92672">);</span>
    <span style="color:#f92672">}</span>

    <span style="color:#75715e">//phone scan for the login
</span><span style="color:#75715e"></span>    <span style="color:#a6e22e">@RequestMapping</span><span style="color:#f92672">(</span>value <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/login/{sessionId}&#34;</span><span style="color:#f92672">,</span> method <span style="color:#f92672">=</span> RequestMethod<span style="color:#f92672">.</span><span style="color:#a6e22e">POST</span><span style="color:#f92672">)</span>
    <span style="color:#a6e22e">@ResponseBody</span>
    <span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">scanWithLogin</span><span style="color:#f92672">(</span><span style="color:#a6e22e">@PathVariable</span><span style="color:#f92672">(</span><span style="color:#e6db74">&#34;sessionId&#34;</span><span style="color:#f92672">)</span> String sessionId<span style="color:#f92672">,</span> <span style="color:#a6e22e">@RequestParam</span> String username<span style="color:#f92672">,</span> <span style="color:#a6e22e">@RequestParam</span> String token<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
        loginService<span style="color:#f92672">.</span><span style="color:#a6e22e">checkTokenWithName</span><span style="color:#f92672">(</span>username<span style="color:#f92672">,</span> token<span style="color:#f92672">);</span>
        <span style="color:#66d9ef">return</span> scanService<span style="color:#f92672">.</span><span style="color:#a6e22e">scanWithLogin</span><span style="color:#f92672">(</span>sessionId<span style="color:#f92672">,</span> username<span style="color:#f92672">);</span>
    <span style="color:#f92672">}</span>
<span style="color:#f92672">}</span>
</code></pre></div><p>这样就可以使用 http://localhost:8433/user/login/user 这样的 url,使用 post 方式,模拟表单<br>
同一个 url,使用 get 的方式,获取的就是二维码的显示页面<br>
这里 index 是定义到一个模板页面,model 中可以设置一些属性在模板文件中进行调用,我这里模板用的是<code>thymeleaf</code></p>
<h3 id="模板文件">模板文件</h3>
<p>放在 src/main/resources/templates 目录下,也就是在生成放置 application.properties 的目录中新建一个 templates 目录,在其中新建一个 index.html,这样 controller 就会使用模板渲染 html
使用了 jquery 和 jquery.qrcode 两个 js 库,其中 jquery 是网络访问使用,qrcode 依赖于 jquery,同时提供 qrcode 的生成</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-html" data-lang="html"><span style="color:#75715e">&lt;!DOCTYPE html&gt;</span>
&lt;<span style="color:#f92672">html</span>
  <span style="color:#a6e22e">xmlns:th</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://www.thymeleaf.org&#34;</span>
  <span style="color:#a6e22e">xmlns:sec</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://www.thymeleaf.org/thymeleaf-extras-springsecurity3&#34;</span>
&gt;
  &lt;<span style="color:#f92672">head</span>&gt;
    &lt;<span style="color:#f92672">meta</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;viewport&#34;</span> <span style="color:#a6e22e">content</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;width=device-width,initial-scale=1&#34;</span> /&gt;
    <span style="color:#75715e">&lt;!--&lt;link th:href=&#34;@{bootstrap/css/bootstrap.min.css}&#34; rel=&#34;stylesheet&#34;/&gt;--&gt;</span>
    <span style="color:#75715e">&lt;!--&lt;link th:href=&#34;@{bootstrap/css/bootstrap-theme.min.css}&#34; rel=&#34;stylesheet&#34;/&gt;--&gt;</span>
    &lt;<span style="color:#f92672">meta</span> <span style="color:#a6e22e">charset</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;UTF-8&#34;</span> /&gt;
    &lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/javascript&#34;</span> <span style="color:#a6e22e">th:src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;@{/js/jquery-3.2.1.min.js}&#34;</span>&gt;&lt;/<span style="color:#f92672">script</span>&gt;
    <span style="color:#75715e">&lt;!--&lt;script type=&#34;text/javascript&#34; th:src=&#34;@{/js/qrcode.js}&#34;&gt;&lt;/script&gt;--&gt;</span>
    &lt;<span style="color:#f92672">script</span>
      <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/javascript&#34;</span>
      <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;http://cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js&#34;</span>
    &gt;&lt;/<span style="color:#f92672">script</span>&gt;
    <span style="color:#75715e">&lt;!--&lt;script type=&#34;text/javascript&#34; src=&#34;../static/js/jquery-3.2.1.min.js&#34;&gt;&lt;/script&gt;--&gt;</span>

    &lt;<span style="color:#f92672">script</span> <span style="color:#a6e22e">th:inline</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;javascript&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text/javascript&#34;</span>&gt;

      <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">makeQrImage</span>(<span style="color:#a6e22e">sessionId</span>) {
          <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">qrcode</span> <span style="color:#f92672">=</span> [[<span style="color:#a6e22e">$</span>{<span style="color:#a6e22e">qrcode</span>}]]
          <span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;#code&#39;</span>).<span style="color:#a6e22e">qrcode</span>(<span style="color:#a6e22e">qrcode</span>);
          <span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;p&#39;</span>).<span style="color:#a6e22e">text</span>(<span style="color:#a6e22e">qrcode</span>)

          <span style="color:#a6e22e">$</span>.<span style="color:#a6e22e">ajax</span>({
              <span style="color:#a6e22e">url</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;./wait/&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">sessionId</span>,
              <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;post&#39;</span>,
              <span style="color:#a6e22e">success</span><span style="color:#f92672">:</span><span style="color:#a6e22e">login</span>,
              <span style="color:#a6e22e">fail</span><span style="color:#f92672">:</span><span style="color:#a6e22e">loginFail</span>
          })
      }

      <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">login</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">result</span>) {
          <span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;p&#39;</span>).<span style="color:#a6e22e">text</span>(<span style="color:#a6e22e">result</span>)
      };

      <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">loginFail</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">result</span>) {
          <span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;p&#39;</span>).<span style="color:#a6e22e">text</span>(<span style="color:#a6e22e">result</span>)
      }

      <span style="color:#a6e22e">$</span>(document).<span style="color:#a6e22e">ready</span>(<span style="color:#66d9ef">function</span> () {
          <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">sessionId</span> <span style="color:#f92672">=</span> [[<span style="color:#a6e22e">$</span>{<span style="color:#a6e22e">sessionId</span>}]]
          <span style="color:#a6e22e">makeQrImage</span>(<span style="color:#a6e22e">sessionId</span>)
      });
    &lt;/<span style="color:#f92672">script</span>&gt;
    &lt;<span style="color:#f92672">style</span>&gt;
      .<span style="color:#a6e22e">qrcode</span> {
        <span style="color:#66d9ef">width</span>: <span style="color:#ae81ff">150</span><span style="color:#66d9ef">px</span>;
        <span style="color:#66d9ef">height</span>: <span style="color:#ae81ff">150</span><span style="color:#66d9ef">px</span>;
      }
    &lt;/<span style="color:#f92672">style</span>&gt;
    &lt;<span style="color:#f92672">title</span>&gt;Title&lt;/<span style="color:#f92672">title</span>&gt;
  &lt;/<span style="color:#f92672">head</span>&gt;
  &lt;<span style="color:#f92672">body</span>&gt;
    &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;code&#34;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
    &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;result&#34;</span>&gt;&lt;<span style="color:#f92672">p</span>&gt;&lt;/<span style="color:#f92672">p</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
  &lt;/<span style="color:#f92672">body</span>&gt;
&lt;/<span style="color:#f92672">html</span>&gt;
</code></pre></div><p>[[${sessionId}]] 就是读取 model 中的 sessionId 属性</p>
<p>同理
[[${qrcode}]]就是 model 中的 qrcode 属性</p>
<p>这里 <code>&lt;script th:inline=&quot;javascript&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</code>
的标签中使用了 th:inline=&quot;javascript&rdquo; 这样的写法,这个就是模板的写法了,让 js 标签内可以识别模板中的变量等等</p>
<p>这里 ajax 中使用了硬编码,可以考虑使用 java 中的 model 传过来,如同 qrcode 的 url 一样,这样就可以在不动 html 的情况下,完成后台 url 的切换</p>
<p>这里其实逻辑比较简单</p>
<h4 id="步骤">步骤</h4>
<p>前端网页: 访问 <code>/user/login</code> GET 方式,提示扫码,然后使用已经登录的手机扫码,同时创建一个 ajax 连接,后台 hold 住此链接等待扫码,使用的是长轮询的方案</p>
<p>手机端:访问<code>/user/login/admin</code>POST 方式,先登录,获取了 token 和 username,然后再使用扫码,传入参数 username,token</p>
<h4 id="mysql-数据库表设计相关逻辑">mysql 数据库表设计(相关逻辑)</h4>
<pre><code>用户表
记录用户相关的数据,包括id,用户名,email,注册时间等信息

登录token表
记录用户token,和token更新时间,token信息
</code></pre>
<p>具体的 java 端实现<br>
上面只是简单的流程步骤,具体的实现还是需要到 service 中去看</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-kotlin" data-lang="kotlin"><span style="color:#66d9ef">package</span> com.kikt.api.service.scan

<span style="color:#66d9ef">import</span> com.kikt.api.exeption.ErrorEnum
<span style="color:#66d9ef">import</span> com.kikt.api.ext.toJson
<span style="color:#66d9ef">import</span> com.kikt.api.service.BaseService
<span style="color:#66d9ef">import</span> com.kikt.api.service.user.LoginService
<span style="color:#66d9ef">import</span> com.kikt.response.Response
<span style="color:#66d9ef">import</span> org.springframework.beans.factory.annotation.Autowired
<span style="color:#66d9ef">import</span> org.springframework.stereotype.Service
<span style="color:#66d9ef">import</span> java.util.*
<span style="color:#66d9ef">import</span> java.util.concurrent.*

<span style="color:#75715e">/**
</span><span style="color:#75715e"> * Created by cai on 2017/8/24.
</span><span style="color:#75715e"> */</span>
@Service
<span style="color:#66d9ef">open</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ScanService</span> : BaseService {

    @Autowired
    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">var</span> loginService: LoginService? = <span style="color:#66d9ef">null</span>

    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">val</span> map: MutableMap&lt;String, LoginSession&gt; = mutableMapOf()

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">getSessionId</span>(): String {
        <span style="color:#66d9ef">val</span> random = UUID.randomUUID().toString()
        map.put(random, LoginSession())
        <span style="color:#66d9ef">return</span> random
    }

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">waitForLogin</span>(sessionId: String): String {
        <span style="color:#66d9ef">val</span> sessionData = map[sessionId] <span style="color:#f92672">?:</span> ErrorEnum.SESSION_SCAN_TIME_OUT.throwError()
        <span style="color:#66d9ef">val</span> waitForLogin: String
        <span style="color:#66d9ef">try</span> {
            waitForLogin = sessionData.waitForLogin()
        } <span style="color:#66d9ef">catch</span>(e: Exception) {
            map.remove(sessionId)
            ErrorEnum.SESSION_SCAN_TIME_OUT.throwError()
        }
        map.remove(sessionId)
        <span style="color:#66d9ef">return</span> waitForLogin
    }

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">scanWithLogin</span>(sessionId: String, username: String): String {
        <span style="color:#66d9ef">val</span> sessionData = map[sessionId] <span style="color:#f92672">?:</span> ErrorEnum.SESSION_NO_FOUNT.throwError()
        <span style="color:#66d9ef">val</span> result = loginService<span style="color:#f92672">?.</span>login(username, <span style="color:#ae81ff">2</span>)
        <span style="color:#66d9ef">if</span> (result != <span style="color:#66d9ef">null</span>) {
            sessionData.login(result)
        }
        <span style="color:#66d9ef">return</span> Response.newSuccessResponse(<span style="color:#e6db74">&#34;成功&#34;</span>).toJson()
    }

}

<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">LoginSession</span> {

    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">val</span> queue: BlockingQueue&lt;String&gt; = LinkedBlockingQueue(<span style="color:#ae81ff">2</span>)

    <span style="color:#66d9ef">companion</span> <span style="color:#66d9ef">object</span> {
        <span style="color:#66d9ef">val</span> TIME_OUT: Long = <span style="color:#ae81ff">60000</span>

        <span style="color:#66d9ef">val</span> threadPool: ExecutorService = Executors.newFixedThreadPool(<span style="color:#ae81ff">30</span>)
    }

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">waitForLogin</span>(): String {
        <span style="color:#66d9ef">val</span> take: String?
        <span style="color:#66d9ef">try</span> {
            runDelayTimeout()
            take = queue.take()
        } <span style="color:#66d9ef">catch</span>(e: InterruptedException) {
            <span style="color:#66d9ef">throw</span> e
        }
        <span style="color:#66d9ef">return</span> take
    }

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">login</span>(result: String) {
        queue.offer(result)
    }

    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">runDelayTimeout</span>() {
        <span style="color:#66d9ef">val</span> currentThread = Thread.currentThread()
        threadPool.execute {
            Thread.sleep(TIME_OUT)
            currentThread.interrupt()
        }
    }
}
</code></pre></div><p>总体思路是:定义一个 map 用于记录 sesstionId,和具体的 LoginSession</p>
<p>LoginSession 中包含一个阻塞队列,在 index 的 ctl 中创建 sessionId 和 loginSession 对象,在访问/wait/sessionId 时调用,等待扫码,称为连接 1</p>
<p>扫码时,创建连接 2,根据 token 检验手机登陆用户,然后根据 sessionId 找到 LoginSession 对象,给队列传入数据,这样 LoginSession.take()返回后结果后,连接 1 返回登陆信息,同时登陆 2 返回成功的信息</p>
<h4 id="优化">优化</h4>
<p>上面的连接 1 中需要设置一个超时时间,超时后返回失败,这里创建一个线程池,30 秒后尝试中断线程,上面</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-kotlin" data-lang="kotlin">    <span style="color:#66d9ef">fun</span> <span style="color:#a6e22e">runDelayTimeout</span>() {
        <span style="color:#66d9ef">val</span> currentThread = Thread.currentThread()
        threadPool.execute {
            Thread.sleep(TIME_OUT)
            currentThread.interrupt()
        }
    }
</code></pre></div><p>执行 60 秒后过时,连接 1 返回失败信息,前端根据失败信息显示刷新重试的样式即可</p>
<h4 id="后记">后记</h4>
<p>总体思路和主要代码都放出来了,具体的实现应该还有更优解,这里我就不尝试了,只起到思路引领</p>

                        </div>

                        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/posts/server/java/spring-boot/encoding-error/">spring boot jdbctemplate mysql emoji 编码错误的问题</a></li>
        
        <li><a href="/posts/server/java/poi/">Poi解析对比excel表格</a></li>
        
        <li><a href="/posts/ios/swift/swift3-class-as-param/">Swift3之将类作为参数</a></li>
        
        <li><a href="/posts/other/rn-weex-my-idea/">RN/Weex的个人看法</a></li>
        
        <li><a href="/posts/ios/ios-toast/">Ios版toast</a></li>
        
    </ul>
</div>


                        <div class="post-meta meta-tags">
                            
                            <ul class="clearfix">
                                
                                <li><a href="http://www.kikt.top/tags/sprintboot">sprintboot</a></li>
                                
                                <li><a href="http://www.kikt.top/tags/java">java</a></li>
                                
                                <li><a href="http://www.kikt.top/tags/%E6%89%AB%E7%A0%81">扫码</a></li>
                                
                                <li><a href="http://www.kikt.top/tags/server">server</a></li>
                                
                            </ul>
                            
                        </div>
                    </article>
                    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "caijinglong/kikt-blog-comment"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
                </div>
            </div>
            <div id="secondary">
    <section class="widget">
        <form id="search" action="//www.google.com/search" method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="http://www.kikt.top">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://www.kikt.top/posts/java/crack/crack1/" title="使用javassist,修改jar包方法实现">使用javassist,修改jar包方法实现</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/github/actions/create/" title="Github action 的开发到发布">Github action 的开发到发布</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/jenkins&#43;fastlane/" title="flutter Jenkins&#43;fastlane 自动化打测试包, 并上传蒲公英">flutter Jenkins&#43;fastlane 自动化打测试包, 并上传蒲公英</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/go/compile-for-android/" title="编译 go 源码为 android 动态库(so)">编译 go 源码为 android 动态库(so)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/focusnode-2/" title="Flutter FocusNode 焦点那点事-(二)">Flutter FocusNode 焦点那点事-(二)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/focusnode-1/" title="Flutter FocusNode 焦点那点事-(一)">Flutter FocusNode 焦点那点事-(一)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/server/caddy/cros_for_local_dev/" title="用 Caddy 解决 web 开发中本地跨域的问题">用 Caddy 解决 web 开发中本地跨域的问题</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/route/navigator-helper2/" title="Navigator Helper2">Navigator Helper2</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/grey-app/" title="flutter 怎么实现app整体灰度">flutter 怎么实现app整体灰度</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/posts/flutter/plugin/flutter-sdk-import-aar/" title="Flutter 插件开发之引入aar到安卓部分 并使用本地maven">Flutter 插件开发之引入aar到安卓部分 并使用本地maven</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title">分类</h3>
<ul class="widget-list">
    
    <li>
        <a href="http://www.kikt.top/categories/android/">android(25)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/caddy/">caddy(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/dart/">dart(5)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/docker/">docker(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/flutter/">flutter(60)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/github/">github(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/go/">go(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/golang/">golang(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/iOS/">iOS(6)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/ios/">ios(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/java/">java(6)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/jetbrains/">jetbrains(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/other/">other(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/python/">python(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/server/">server(5)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/spring/">spring(3)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/tools/">tools(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/%E6%9D%82%E9%A1%B9/">杂项(1)</a>
    </li>
    
    <li>
        <a href="http://www.kikt.top/categories/%E6%B6%82%E9%B8%A6/">涂鸦(1)</a>
    </li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title">标签</h3>
<div class="tagcloud">
    
    <a href="http://www.kikt.top/tags/10/">10</a>
    
    <a href="http://www.kikt.top/tags/2.3/">2.3</a>
    
    <a href="http://www.kikt.top/tags/Clipboard/">Clipboard</a>
    
    <a href="http://www.kikt.top/tags/Javassist/">Javassist</a>
    
    <a href="http://www.kikt.top/tags/Migrate/">Migrate</a>
    
    <a href="http://www.kikt.top/tags/aar/">aar</a>
    
    <a href="http://www.kikt.top/tags/actions/">actions</a>
    
    <a href="http://www.kikt.top/tags/aidl/">aidl</a>
    
    <a href="http://www.kikt.top/tags/android/">android</a>
    
    <a href="http://www.kikt.top/tags/androidQ/">androidQ</a>
    
    <a href="http://www.kikt.top/tags/androidX/">androidX</a>
    
    <a href="http://www.kikt.top/tags/apk/">apk</a>
    
    <a href="http://www.kikt.top/tags/app/">app</a>
    
    <a href="http://www.kikt.top/tags/appcode/">appcode</a>
    
    <a href="http://www.kikt.top/tags/azure/">azure</a>
    
    <a href="http://www.kikt.top/tags/ble/">ble</a>
    
    <a href="http://www.kikt.top/tags/bottomsheet/">bottomsheet</a>
    
    <a href="http://www.kikt.top/tags/butterknife/">butterknife</a>
    
    <a href="http://www.kikt.top/tags/c/">c</a>
    
    <a href="http://www.kikt.top/tags/caddy/">caddy</a>
    
    <a href="http://www.kikt.top/tags/camera/">camera</a>
    
    <a href="http://www.kikt.top/tags/cameraX/">cameraX</a>
    
    <a href="http://www.kikt.top/tags/channel/">channel</a>
    
    <a href="http://www.kikt.top/tags/cocoapods/">cocoapods</a>
    
    <a href="http://www.kikt.top/tags/cupertino/">cupertino</a>
    
    <a href="http://www.kikt.top/tags/dart/">dart</a>
    
    <a href="http://www.kikt.top/tags/dart-2.6/">dart-2.6</a>
    
    <a href="http://www.kikt.top/tags/desktop/">desktop</a>
    
    <a href="http://www.kikt.top/tags/dialog/">dialog</a>
    
    <a href="http://www.kikt.top/tags/dmg/">dmg</a>
    
    <a href="http://www.kikt.top/tags/doc/">doc</a>
    
    <a href="http://www.kikt.top/tags/docker/">docker</a>
    
    <a href="http://www.kikt.top/tags/docker-compose/">docker-compose</a>
    
    <a href="http://www.kikt.top/tags/excel/">excel</a>
    
    <a href="http://www.kikt.top/tags/exists/">exists</a>
    
    <a href="http://www.kikt.top/tags/faq/">faq</a>
    
    <a href="http://www.kikt.top/tags/fastlane/">fastlane</a>
    
    <a href="http://www.kikt.top/tags/ffi/">ffi</a>
    
    <a href="http://www.kikt.top/tags/ffmpeg/">ffmpeg</a>
    
    <a href="http://www.kikt.top/tags/flexmark/">flexmark</a>
    
    <a href="http://www.kikt.top/tags/flutter/">flutter</a>
    
    <a href="http://www.kikt.top/tags/flutter-web/">flutter-web</a>
    
    <a href="http://www.kikt.top/tags/focus/">focus</a>
    
    <a href="http://www.kikt.top/tags/focusNode/">focusNode</a>
    
    <a href="http://www.kikt.top/tags/form/">form</a>
    
    <a href="http://www.kikt.top/tags/framework/">framework</a>
    
    <a href="http://www.kikt.top/tags/github/">github</a>
    
    <a href="http://www.kikt.top/tags/go/">go</a>
    
    <a href="http://www.kikt.top/tags/golang/">golang</a>
    
    <a href="http://www.kikt.top/tags/gradle/">gradle</a>
    
    <a href="http://www.kikt.top/tags/http/">http</a>
    
    <a href="http://www.kikt.top/tags/iOS/">iOS</a>
    
    <a href="http://www.kikt.top/tags/ide/">ide</a>
    
    <a href="http://www.kikt.top/tags/idea/">idea</a>
    
    <a href="http://www.kikt.top/tags/index/">index</a>
    
    <a href="http://www.kikt.top/tags/inside/">inside</a>
    
    <a href="http://www.kikt.top/tags/ios/">ios</a>
    
    <a href="http://www.kikt.top/tags/java/">java</a>
    
    <a href="http://www.kikt.top/tags/jenkins/">jenkins</a>
    
    <a href="http://www.kikt.top/tags/jetbrains/">jetbrains</a>
    
    <a href="http://www.kikt.top/tags/jsdelivr/">jsdelivr</a>
    
    <a href="http://www.kikt.top/tags/json/">json</a>
    
    <a href="http://www.kikt.top/tags/json_serializable/">json_serializable</a>
    
    <a href="http://www.kikt.top/tags/junit/">junit</a>
    
    <a href="http://www.kikt.top/tags/library/">library</a>
    
    <a href="http://www.kikt.top/tags/live-template/">live-template</a>
    
    <a href="http://www.kikt.top/tags/loadmore/">loadmore</a>
    
    <a href="http://www.kikt.top/tags/log/">log</a>
    
    <a href="http://www.kikt.top/tags/mac/">mac</a>
    
    <a href="http://www.kikt.top/tags/macos/">macos</a>
    
    <a href="http://www.kikt.top/tags/maven/">maven</a>
    
    <a href="http://www.kikt.top/tags/mysql/">mysql</a>
    
    <a href="http://www.kikt.top/tags/navigationbar/">navigationbar</a>
    
    <a href="http://www.kikt.top/tags/navigator/">navigator</a>
    
    <a href="http://www.kikt.top/tags/ndk/">ndk</a>
    
    <a href="http://www.kikt.top/tags/nginx/">nginx</a>
    
    <a href="http://www.kikt.top/tags/oc/">oc</a>
    
    <a href="http://www.kikt.top/tags/opencv/">opencv</a>
    
    <a href="http://www.kikt.top/tags/poi/">poi</a>
    
    <a href="http://www.kikt.top/tags/pub/">pub</a>
    
    <a href="http://www.kikt.top/tags/python/">python</a>
    
    <a href="http://www.kikt.top/tags/retrofit/">retrofit</a>
    
    <a href="http://www.kikt.top/tags/route/">route</a>
    
    <a href="http://www.kikt.top/tags/server/">server</a>
    
    <a href="http://www.kikt.top/tags/so/">so</a>
    
    <a href="http://www.kikt.top/tags/spp/">spp</a>
    
    <a href="http://www.kikt.top/tags/sprintboot/">sprintboot</a>
    
    <a href="http://www.kikt.top/tags/swift/">swift</a>
    
    <a href="http://www.kikt.top/tags/tap/">tap</a>
    
    <a href="http://www.kikt.top/tags/thymeleaf/">thymeleaf</a>
    
    <a href="http://www.kikt.top/tags/tips/">tips</a>
    
    <a href="http://www.kikt.top/tags/toast/">toast</a>
    
    <a href="http://www.kikt.top/tags/transition/">transition</a>
    
    <a href="http://www.kikt.top/tags/ui/">ui</a>
    
    <a href="http://www.kikt.top/tags/utf8/">utf8</a>
    
    <a href="http://www.kikt.top/tags/yield/">yield</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%8C%E8%BF%9B%E5%88%B6/">二进制</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%A4%E5%8F%89/">交叉</a>
    
    <a href="http://www.kikt.top/tags/%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91/">交叉编译</a>
    
    <a href="http://www.kikt.top/tags/%E4%BB%8B%E7%BB%8D/">介绍</a>
    
    <a href="http://www.kikt.top/tags/%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83/">代码规范</a>
    
    <a href="http://www.kikt.top/tags/%E5%86%B2%E7%AA%81/">冲突</a>
    
    <a href="http://www.kikt.top/tags/%E5%8A%A8%E6%80%81/">动态</a>
    
    <a href="http://www.kikt.top/tags/%E5%8F%91%E5%B8%83/">发布</a>
    
    <a href="http://www.kikt.top/tags/%E5%8F%AF%E6%89%A7%E8%A1%8C/">可执行</a>
    
    <a href="http://www.kikt.top/tags/%E5%9B%BE%E5%BA%8A/">图床</a>
    
    <a href="http://www.kikt.top/tags/%E5%9F%8E%E5%B8%82/">城市</a>
    
    <a href="http://www.kikt.top/tags/%E5%A4%A7%E6%96%87%E4%BB%B6/">大文件</a>
    
    <a href="http://www.kikt.top/tags/%E5%B7%A5%E5%85%B7/">工具</a>
    
    <a href="http://www.kikt.top/tags/%E5%B7%B2%E6%9C%89%E9%A1%B9%E7%9B%AE/">已有项目</a>
    
    <a href="http://www.kikt.top/tags/%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83/">开发环境</a>
    
    <a href="http://www.kikt.top/tags/%E6%80%BB%E7%BB%93/">总结</a>
    
    <a href="http://www.kikt.top/tags/%E6%85%A2/">慢</a>
    
    <a href="http://www.kikt.top/tags/%E6%89%93%E5%8C%85/">打包</a>
    
    <a href="http://www.kikt.top/tags/%E6%89%AB%E7%A0%81/">扫码</a>
    
    <a href="http://www.kikt.top/tags/%E6%8F%92%E4%BB%B6/">插件</a>
    
    <a href="http://www.kikt.top/tags/%E6%96%87%E6%A1%A3/">文档</a>
    
    <a href="http://www.kikt.top/tags/%E6%A8%A1%E6%9D%BF/">模板</a>
    
    <a href="http://www.kikt.top/tags/%E6%B8%B2%E6%9F%93/">渲染</a>
    
    <a href="http://www.kikt.top/tags/%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/">源码解析</a>
    
    <a href="http://www.kikt.top/tags/%E7%81%B0%E5%BA%A6/">灰度</a>
    
    <a href="http://www.kikt.top/tags/%E7%82%B9%E5%87%BB/">点击</a>
    
    <a href="http://www.kikt.top/tags/%E7%84%A6%E7%82%B9/">焦点</a>
    
    <a href="http://www.kikt.top/tags/%E7%88%AC%E8%99%AB/">爬虫</a>
    
    <a href="http://www.kikt.top/tags/%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/">状态管理</a>
    
    <a href="http://www.kikt.top/tags/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/">百度地图</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E7%A0%81/">编码</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E7%A8%8B%E6%8A%80%E5%B7%A7/">编程技巧</a>
    
    <a href="http://www.kikt.top/tags/%E7%BC%96%E8%AF%91/">编译</a>
    
    <a href="http://www.kikt.top/tags/%E7%BF%BB%E8%AF%91/">翻译</a>
    
    <a href="http://www.kikt.top/tags/%E8%93%9D%E7%89%99/">蓝牙</a>
    
    <a href="http://www.kikt.top/tags/%E8%A1%A8%E5%8D%95/">表单</a>
    
    <a href="http://www.kikt.top/tags/%E8%B7%AF%E7%94%B1/">路由</a>
    
    <a href="http://www.kikt.top/tags/%E8%BF%87%E5%9C%BA%E5%8A%A8%E7%94%BB/">过场动画</a>
    
    <a href="http://www.kikt.top/tags/%E9%9A%90%E7%A7%81/">隐私</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="https://github.com/Caijinglong" title="我的Github">我的Github</a>
        </li>
        
        <li>
            <a target="_blank" href="https://flutter.dev" title="flutter 官网">flutter 官网</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="http://www.kikt.top/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
        </div>
    </div>
</div>
<footer id="footer">
    <div class="container">
        <div>
            <p>如果我的blog对您有帮助,而您愿意捐赠 😆, 可以用下面的二维码</p>
            <img style="width:5rem;" src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424141834.png"/>
            <img style="width:5rem; padding-left: 2rem;" 
            src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424141931.png"/>
            <img style="width:5rem; padding-left: 2rem;" 
            src="https://dev.azure.com/cjlspy/844861b8-ee45-48a3-b430-b974684baaaa/_apis/git/repositories/bf4da1c1-1cfa-4f54-8a75-745cce2b737c/items?versionDescriptor%5Bversion%5D=master&versionDescriptor%5BversionOptions%5D=0&versionDescriptor%5BversionType%5D=0&resolveLfs=true&%24format=octetStream&api-version=5.0&path=%2F20190424142013.png"/>
        </div>
        &copy; 2018 <a href="http://www.kikt.top">caijinglong的博客 By caijinglong</a>.
        Powered by <a rel="nofollow noreferer noopener" href="https://gohugo.io" target="_blank">Hugo</a>.
        <a href="http://www.flysnow.org/" target="_blank">Theme</a> based on <a href="https://github.com/rujews/maupassant-hugo" target="_blank">maupassant</a>.<br/>
        本站所有内容基于<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" style="color:coral">CC4.0</a>协议发布,需要转载必须署名
        <br/>
        如果有问题可以<a href="mailto:cjl_spy@163.com">email联系我</a>
        <br/>
        京ICP备18038473号-1
        
    </div>
</footer>


    <script type="text/javascript" src="/js/prism.js" async="true"></script>
    <script type="text/javascript">
    
    (function(){
        $("pre code").parent().addClass("line-numbers")
    }())

    window.MathJax = {
        tex2jax: {
            inlineMath: [ ['$','$'] ],
            processEscapes: true
        }
    };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src="/js/totop.js?v=0.0.0" async=""></script>



<script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




</body>
</html>
